package com.dgut.lotterySystem.service.impl;

import com.dgut.lotterySystem.common.errorcode.ServiceErrorCodeConstants;
import com.dgut.lotterySystem.common.pojo.exception.ServiceException;
import com.dgut.lotterySystem.common.utils.*;
import com.dgut.lotterySystem.controller.param.UserLoginParam;
import com.dgut.lotterySystem.controller.param.UserMessageLoginParam;
import com.dgut.lotterySystem.controller.param.UserPasswordLoginParam;
import com.dgut.lotterySystem.controller.param.UserRegisterParam;
import com.dgut.lotterySystem.dao.dataObject.Encrypt;
import com.dgut.lotterySystem.dao.dataObject.UserDO;
import com.dgut.lotterySystem.dao.dataObject.UserInfoDO;
import com.dgut.lotterySystem.dao.mapper.UserMapper;
import com.dgut.lotterySystem.service.IUserService;
import com.dgut.lotterySystem.service.dto.UserInfoDTO;
import com.dgut.lotterySystem.service.dto.UserLoginDTO;
import com.dgut.lotterySystem.service.dto.UserRegisterDTO;
import com.dgut.lotterySystem.service.enums.IdentityEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private VerificationCodeServiceImpl codeService;
    @Override
    public UserRegisterDTO register(UserRegisterParam param) {

        //参数校对
        checkRegisterInfo(param);
        //加密(构造dao请求)
        UserDO userDO=new UserDO();
        userDO.setUserName(param.getUserName());
        userDO.setEmail(param.getEmail());
        userDO.setPhoneNumber(new Encrypt(param.getPhoneNumber()));
        userDO.setIdentity(param.getIdentity());

        //如果提交的参数有密码，说明就是注册管理员用户
        if(StringUtils.hasText(param.getPassword())){
            //获取盐,加密密码
            String salt= UUIDUtil.UUID_32();
            userDO.setSalt(salt);
            //校验密码是否为空
            if(!StringUtils.hasText(param.getPassword()))
                throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
            String password= PasswordUtil.md5Second(param.getPassword(),salt);
            userDO.setPassword(password);
        }

        //保存数据
        int ret=userMapper.insert(userDO);
        if(ret!=1){
            throw new ServiceException(ServiceErrorCodeConstants.PICTURE_SAVE_ERROR);
        }

        //构造返回
        UserRegisterDTO userRegisterDTO=new UserRegisterDTO();
        userRegisterDTO.setUserId(userDO.getId());
        return userRegisterDTO;
    }

    /**
     * 登录
     * @param param
     * @return
     */
    @Override
    public UserLoginDTO login(UserLoginParam param){
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        //判断参数
        if(param==null) throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_NULL);
        if(param instanceof UserMessageLoginParam loginParam){
            userLoginDTO=loginByMessage(loginParam);
        }else if(param instanceof UserPasswordLoginParam loginParam){
            userLoginDTO=loginByPassword(loginParam);
        }else{
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_ERROR);
        }
        return userLoginDTO;
    }

    @Override
    public List<UserInfoDTO> getUserInfoList(IdentityEnum forName) {
        String identityStr=(forName==null?null:forName.name());
        List<UserInfoDO> userInfoDOList=userMapper.selectUserInfoListByIdentity(identityStr);
        List<UserInfoDTO> userInfoDTOlIST=userInfoDOList.stream().map(
                userInfoDO ->{
                    UserInfoDTO userInfoDTO=new UserInfoDTO();
                    userInfoDTO.setId(userInfoDO.getId());
                    userInfoDTO.setUserName(userInfoDO.getUserName());
                    userInfoDTO.setEmail(userInfoDO.getEmail());
                    userInfoDTO.setPhoneNumber(userInfoDO.getPhoneNumber().getValue());
                    userInfoDTO.setIdentity(userInfoDO.getIdentity().name());
                    return userInfoDTO;
                }).collect(Collectors.toList());
        return userInfoDTOlIST;
    }

    private UserLoginDTO loginByMessage(UserMessageLoginParam param){
        //短信验证，检查手机号码就好
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        UserDO userDO=new UserDO();
        if(!RegexUtil.checkMobile(param.getLoginMobile())){
            //校验手机号码
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        //根据手机号码查询对象
        userDO=userMapper.selectByPhoneNumber(new Encrypt(param.getLoginMobile()));
        if(userDO==null){
            //校验对象是否为空
            throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_NOT_EXISTS);
        }else if(!StringUtils.hasText(userDO.getIdentity())
                 ||!param.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())){
            //校验对象是否强制身份信息登录
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_IDENTITY_ERROR);
        }
        //校验验证码
        //从缓存中获取验证码
        String code= codeService.getVerificationCode(param.getLoginMobile());
        if(!code.equals(param.getVerificationCode())){
            throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);
        }

        //构造JWT
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("name",userDO.getUserName());
        String token= JWTUtil.genJwt(claim);

        //构造返回结果
        userLoginDTO.setToken(token);
        userLoginDTO.setMandatoryIdentity(IdentityEnum.forName(userDO.getIdentity()));
        return userLoginDTO;
    }
    private UserLoginDTO loginByPassword(UserPasswordLoginParam param){
        //密码登录，要检查邮箱和手机号码
        UserLoginDTO userLoginDTO=new UserLoginDTO();
        UserDO userDO=new UserDO();
        //检查是什么方式登录，并查表返回
        if(param==null){
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_NULL);
        }else if(RegexUtil.checkMobile(param.getLoginName())){
           userDO=userMapper.selectByPhoneNumber(new Encrypt(param.getLoginName()));
        }else if(RegexUtil.checkMail(param.getLoginName())){
            userDO=userMapper.selectByEmail(param.getLoginName());
        }else{
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_ERROR);
        }
        //检查，表返回的对象
        if(userDO==null){
            throw new ServiceException(ServiceErrorCodeConstants.USER_INFO_NOT_EXISTS);
        }else if(!StringUtils.hasText(param.getMandatoryIdentity())
                ||!param.getMandatoryIdentity().equalsIgnoreCase(userDO.getIdentity())){
            //校验对象身份信息是否强制登录
            throw new ServiceException(ServiceErrorCodeConstants.LOGIN_PARAM_IDENTITY_ERROR);
        }else if(param.getPassword()==null
                ||!userDO.getPassword().equals(PasswordUtil.md5Second(param.getPassword(),userDO.getSalt()))){
            //校验密码是否正确
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }

        //构造JWT
        Map<String,Object> claim=new HashMap<>();
        claim.put("id",userDO.getId());
        claim.put("name",userDO.getUserName());
        String token= JWTUtil.genJwt(claim);

        //构造返回结果
        userLoginDTO.setToken(token);
        userLoginDTO.setMandatoryIdentity(IdentityEnum.forName(userDO.getIdentity()));
        return userLoginDTO;

    }

    private void checkRegisterInfo(UserRegisterParam param){
        if(null==param){
            throw new ServiceException(ServiceErrorCodeConstants.REGISTER_PARAM_NULL);
        }
        //姓名
        if(param.getUserName()==null){
            throw new ServiceException(ServiceErrorCodeConstants.NAME_ERROR);
        }
        //邮箱
        if(!RegexUtil.checkMail(param.getEmail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        //电话号码
        if(!RegexUtil.checkMobile(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        //校验身份信息
        if(null==IdentityEnum.forName(param.getIdentity())){
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }
        //校验管理者的密码为必填
        if(param.getIdentity().equalsIgnoreCase(IdentityEnum.ADMIN.name())&& !StringUtils.hasText(param.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_IS_EMPTY);
        }
        //如果有密码，校验密码,至少6位
        if(StringUtils.hasText(param.getPassword())
                &&!RegexUtil.checkPassword(param.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }

        //校验邮箱是否被使用
        if(checkMailUsed(param.getEmail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_USED);
        }
        //校验手机号码是否被使用
        if(checkPoneNumberUsed(param.getPhoneNumber())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_USED);
        }

    }

    /**
     * 校验手机号码是否被使用
     * @param phoneNumber
     * @return
     */
    private boolean checkPoneNumberUsed(String phoneNumber) {
        int ret=userMapper.countByPhoneNumber(new Encrypt(phoneNumber));
        System.out.println("电话号码个数："+ret);
        return ret>0;
    }

    /**
     * 校验邮箱是否被使用
     * @param mail
     * @return
     */
    private boolean checkMailUsed(String mail){
        int ret=userMapper.countByMail(mail);
        return ret>0;
    }
}
